﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using XinMai.FreeSql;
using XinMai.FreeSql.Extensions;
using XinMai.IDAL;

namespace XinMai.DAL
{
    /// <summary>
    /// 实现基本接口，继承<see cref="IDAL.IBaseDAL{T}"/>基础接口
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseDAL<T> : IBaseDAL<T> where T : Entity.Entity<long>
    {
        private readonly IMultiRepository<T> _repository;
        private readonly IFreeSql _freesql;
        public BaseDAL(string db, IFreeSql freeSql, IMultiRepository<T> repository)
        {
            _freesql = freeSql;
            _freesql.Change(db);//数据库切换
            _repository = repository;
        }

        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <returns></returns>
        public List<T> GetList()
        {
            var result = _repository.GetList();
            return result;
        }

        /// <summary>
        /// 根据条件获取数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public List<T> GetList(Expression<Func<T, bool>> predicate)
        {
            var result = _repository.GetList(predicate);
            return result;
        }

        /// <summary>
        /// 异步方式获取所有数据
        /// </summary>
        /// <returns></returns>
        public async Task<List<T>> GetListAsync()
        {
            var result = await _repository.GetListAsync();
            return result;
        }

        /// <summary>
        /// 根据条件异步获取数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public async Task<List<T>> GetListAsync(Expression<Func<T, bool>> predicate)
        {
            var result = await _repository.GetListAsync(predicate);
            return result;
        }

        /// <summary>
        /// 分页获取数据
        /// </summary>
        /// <typeparam name="TMember"></typeparam>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="predicate"></param>
        /// <param name="sorting"></param>
        /// <param name="sortingType"></param>
        /// <returns></returns>
        public (List<T> items, long count) GetPageList<TMember>(int page, int pageSize, Expression<Func<T, bool>> predicate = null, Expression<Func<T, TMember>> sorting = null, SortingType sortingType = SortingType.Ascending)
        {
            List<T> result = new List<T>();
            if (predicate != null)
                predicate = predicate.And(p => !p.IsFrozen.Value);
            long count = 0;
            if (page >= 1)
            {
                (result, count) = _repository.GetPagedList(page, pageSize, predicate, sorting, sortingType);
            }
            else
            {
                result = _repository.GetList(predicate, sorting, sortingType);
                count = result.Count;
            }
            return (result,count);
        }

        /// <summary>
        /// 分页异步获取数据
        /// </summary>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public async Task<(List<T> items, long count)> GetPageListAsync(int page,
            int pageSize, Expression<Func<T, bool>> predicate = null)
        {
            List<T> result = new List<T>();
            System.Linq.Expressions.Expression<Func<T, DateTime?>> sorting = s => s.CreateTime;
            if (predicate != null)
                predicate = predicate.And(p => !p.IsFrozen.Value);
            long count = 0;
            if (page >= 1)
            {
                (result, count) = await _repository.GetPagedListAsync(page, pageSize, predicate, sorting, SortingType.Descending);
            }
            else
            {
                result = await _repository.GetListAsync(predicate, sorting, SortingType.Descending);
                count = result.Count;
            }
            return (result, count);
        }

        /// <summary>
        /// 分页异步获取数据
        /// </summary>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="predicate"></param>
        /// <param name="sorting"></param>
        /// <param name="sortingType"></param>
        /// <returns></returns>
        public async Task<(List<T> items, long count)> GetPageListAsync<TMember>(int page,
            int pageSize,
            Expression<Func<T, bool>> predicate = null,
            Expression<Func<T, TMember>> sorting = null,
            SortingType sortingType = SortingType.Ascending)
        {
            List<T> result = new List<T>();
            if (predicate != null)
                predicate = predicate.And(p => !p.IsFrozen.Value);
            long count = 0;
            if (page >= 1)
            {
                (result, count) = await _repository.GetPagedListAsync(page, pageSize, predicate, sorting, sortingType);
            }
            else
            {
                result = await _repository.GetListAsync(predicate, sorting, sortingType);
                count = result.Count;
            }
            return (result, count);
        }

        /// <summary>
        /// 获取单个实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public T GetSingle(long id)
        {
            var result = _repository.GetEntityById(id);
            return result;
        }

        /// <summary>
        /// 根据条件获取单个实体
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public T GetSingle(Expression<Func<T, bool>> predicate)
        {
            var result = _repository.GetEntity(predicate);
            return result;
        }

        /// <summary>
        /// 根据主键获取单个实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<T> GetSingleAsync(long id)
        {
            var result = await _repository.GetEntityByIdAsync(id);
            return result;
        }

        /// <summary>
        /// 根据条件获取单个实体
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public async Task<T> GetSingleAsync(Expression<Func<T, bool>> predicate)
        {
            var result = await _repository.GetEntityAsync(predicate);
            return result;
        }

        /// <summary>
        /// 根据条件获取总记录数
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public long Count(Expression<Func<T, bool>> predicate)
        {
            var result = _repository.Count(predicate);
            return result;
        }

        /// <summary>
        /// 根据条件异步获取总记录数
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public async Task<long> CountAsync(Expression<Func<T, bool>> predicate)
        {
            var result = await _repository.CountAsync(predicate);
            return result;
        }

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public T Insert(T t)
        {
            var result = _repository.Insert(t);
            return result;
        }

        /// <summary>
        /// 批量插入数据
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public List<T> Insert(List<T> t)
        {
            var result = _repository.Insert(t);
            return result;
        }

        /// <summary>
        /// 异步插入数据
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<T> InsertAsync(T t)
        {
            var result = await _repository.InsertAsync(t);
            return result;
        }

        /// <summary>
        /// 异步批量插入数据
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<List<T>> InsertAsync(List<T> t)
        {
            var result = await _repository.InsertAsync(t);
            return result;
        }

        /// <summary>
        /// 修改单个实体
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool Update(T t)
        {
            var count = _repository.Update(t);
            return count > 0;
        }

        /// <summary>
        /// 根据条件修改单个实体
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public bool Update(Expression<Func<T, bool>> predicate, Action<T> action)
        {
            var count = _repository.Update(predicate, action);
            return count > 0;
        }

        /// <summary>
        /// 批量修改实体
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool Update(List<T> t)
        {
            var count = _repository.Update(t);
            return count > 0;
        }

        /// <summary>
        /// 异步修改实体
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(T t)
        {
            var count = await _repository.UpdateAsync(t);
            return count > 0;
        }

        /// <summary>
        /// 根据条件，异步修改实体
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(Expression<Func<T, bool>> predicate, Action<T> action)
        {
            var count = await _repository.UpdateAsync(predicate, action);
            return count > 0;
        }

        /// <summary>
        /// 批量修改实体
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(List<T> t)
        {
            var count = await _repository.UpdateAsync(t);
            return count > 0;
        }

        /// <summary>
        /// 事务执行
        /// </summary>
        /// <param name="handler"></param>
        public bool Transaction(Action handler)
        {
            return _repository.Transaction(handler);
        }
    }
}
